﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace OkTool.Util
{
    /// <summary>
    /// 
    /// </summary>
    public class EncodingUtil
    {
        /// <summary>
        /// ISO-8859-1
        /// </summary>
        public static  String ISO_8859_1 = "ISO-8859-1";

        /// <summary>
        /// UTF-8
        /// </summary>
        public static  String UTF_8 = "UTF-8";

        /// <summary>
        /// GBK
        /// </summary>
        public static  String GBK = "GBK";

        /// <summary>
        /// 解析字符串编码为Charset对象，解析失败返回系统默认编码
        /// </summary>
        /// <param name="charsetName"></param>
        /// <returns></returns>
        public static Encoding Parse(String charsetName)
        {
            return Parse(charsetName, Encoding.Default);
        }


        /// <summary>
        /// 解析字符串编码为Charset对象，解析失败返回默认编码
        /// </summary>
        /// <param name="charsetName">字符集，为空则返回默认字符集</param>
        /// <param name="defaultEncoding">解析失败使用的默认编码</param>
        /// <returns></returns>
        public static Encoding Parse(string charsetName,Encoding defaultEncoding)
        {
            if (StrUtil.IsBlank(charsetName))
            {
                return defaultEncoding;
            }
            Encoding result;
            try
            {
                result = Encoding.GetEncoding(charsetName);
            }
            catch (Exception)
            {
                result = defaultEncoding;
            }
            return result;
        }


        /// <summary>
        /// url编码
        /// </summary>
        /// <param name="text"></param>
        /// <param name="noEncodeAlphaNumeric">不需要编码【字母数字.-】可以把此参数设置为真</param>
        /// <param name="isUtf8">先把文本转换成UTF8编码,再编码成URL</param>
        /// <returns></returns>
        public static string UrlEncode(string text, bool noEncodeAlphaNumeric = false, bool isUtf8 = false)
        {
            if (string.IsNullOrEmpty(text))
                return "";

            byte[] bytes;
            if (isUtf8)
                bytes = Encoding.UTF8.GetBytes(text);
            else
                bytes = Encoding.Default.GetBytes(text);

            StringBuilder result = new StringBuilder();
            for (int i = 0; i < bytes.Length; i++)
            {
                string temp = bytes[i].ToString("X");
                if (temp.Length < 2)
                    temp = "0" + temp;

                if (noEncodeAlphaNumeric && ((bytes[i] > 44 && bytes[i] < 58 && bytes[i] != 47) || (bytes[i] > 64 && bytes[i] < 91) || (bytes[i] > 96 && bytes[i] < 123)))
                {
                    result.Append((char)bytes[i]);
                }
                else
                {
                    result.Append("%" + temp);
                }
            }
            return result.ToString();
        }

        /// <summary>
        /// 转换字符串的字符集编码
        /// </summary>
        /// <param name="source"></param>
        /// <param name="srcCharset">源字符集，默认ISO-8859-1</param>
        /// <param name="destCharset">目标字符集，默认UTF-8</param>
        /// <returns></returns>
        public static String Convert(String source, String srcCharset, String destCharset)
        {
            return Convert(source, Encoding.GetEncoding(srcCharset), Encoding.GetEncoding(destCharset));
        }

        /// <summary>
        /// 转换字符串的字符集编码
        /// <list type="number">
        /// <item>GB2312转UTF8,Convert("我我",Encoding.UTF8,Encoding.GetEncoding("GB2312"))</item>
        /// <item>UTF8转GB2312,Convert("鎴戞垜",Encoding.GetEncoding("GB2312"),Encoding.UTF8)</item>
        /// </list>
        ///
        /// </summary>
        /// <param name="source"></param>
        /// <param name="srcCharset">编码字符集，默认ISO-8859-1</param>
        /// <param name="destCharset">解码字符集，默认UTF-8</param>
        /// <returns></returns>
        public static string Convert(string source,Encoding srcCharset ,Encoding destCharset)
        { 
            if (null == srcCharset)
            {
                srcCharset = Parse(ISO_8859_1);
            }

            if (null == destCharset)
            {
                destCharset = Parse(UTF_8);
            }

            if (StrUtil.IsBlank(source) || srcCharset == destCharset)
            {
                return source;
            }

            byte[] srcBytes = srcCharset.GetBytes(source);
            return destCharset.GetString(srcBytes);
          
        }

        /// <summary>
        /// 转换字符串的字符集编码
        /// <list type="number">
        /// <item>GB2312转UTF8,Convert("我我",Encoding.GetEncoding("GB2312"),Encoding.UTF8)</item>
        /// <item>UTF8转GB2312,Convert("鎴戞垜",Encoding.UTF8,Encoding.GetEncoding("GB2312"))</item>
        /// </list>
        /// </summary>
        /// <param name="source"></param>
        /// <param name="srcCharset">编码字符集，默认ISO-8859-1</param>
        /// <param name="destCharset">解码字符集，默认UTF-8</param>
        /// <returns></returns>
        public static string Convert2(string source, Encoding srcCharset, Encoding destCharset)
        {
            if (null == srcCharset)
            {
                srcCharset = Parse(ISO_8859_1);
            }

            if (null == destCharset)
            {
                destCharset = Parse(UTF_8);
            }

            if (StrUtil.IsBlank(source) || srcCharset == destCharset)
            {
                return source;
            }
            byte[] srcBytes = srcCharset.GetBytes(source);
            byte[] desBytes = Encoding.Convert(srcCharset, destCharset, srcBytes);
            return srcCharset.GetString(desBytes);
        }

        /// <summary>
        /// 转换文件编码
        /// <para>此方法用于转换文件编码，读取的文件实际编码必须与指定的srcCharset编码一致，否则导致乱码</para>
        /// </summary>
        /// <param name="file"></param>
        /// <param name="srcCharset"></param>
        /// <param name="destCharset"></param>
        /// <returns></returns>
        public static FileInfo Convert(FileInfo file, Encoding srcCharset, Encoding destCharset)
        {
             String str = File.ReadAllText(file.FullName, srcCharset);
             File.WriteAllText(file.FullName, str, destCharset);
             return file;
        }

        /// <summary>
        /// 将网页返回的数据解码
        /// </summary>
        /// <param name="URL"></param>
        /// <param name="isUTF8">先将文本串解码为文本,再从UTF8转成GBK编码</param>
        /// <returns></returns>
        public static string DecodeUrl(string URL, bool? isUTF8 = null)
        {
            int Len = URL.Length;
            int loopCounter = 0;
            string HEX = "0123456789ABCDEF";
            string target = "";

            while (loopCounter < Len)
            {
                if (URL[loopCounter] != '%')
                {
                    target += URL[loopCounter];
                }
                else
                {
                    loopCounter++;
                    int H = HEX.IndexOf(char.ToUpper(URL[loopCounter])) * 16;
                    loopCounter++;
                    int L = HEX.IndexOf(char.ToUpper(URL[loopCounter]));
                    target += (char)(H + L);
                }
                loopCounter++;
            }

            if (isUTF8 == true)
            {
                Encoding utf8 = Encoding.GetEncoding("utf-8");
                Encoding gb2312 = Encoding.GetEncoding("gb2312");
                byte[] utfBytes = utf8.GetBytes(target);
                byte[] gbBytes = Encoding.Convert(utf8, gb2312, utfBytes);
                target = gb2312.GetString(gbBytes);
            }

            return target;
        }
    }
}
